package com.hl.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hl.Util.CheckToken;
import com.hl.Util.RedisUtil;
import com.hl.Util.SaltEncryption;
import com.hl.Util.TokenUtils;
import com.hl.entity.Class;
import com.hl.entity.User;
import com.hl.entity.UserClassRel;
import com.hl.entity.UserRole;
import com.hl.service.UserClassRelService;
import com.hl.service.impl.ClassServiceImpl;
import com.hl.service.impl.UserClassRelServiceImpl;
import com.hl.service.impl.UserRoleServiceImpl;
import com.hl.service.impl.UserServiceImpl;
import com.hl.vo.ClassMateInfo;
import com.hl.vo.CommonResult;
import com.hl.vo.TokenVo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @Date 2022/01/11 16:15
 * @created by hl
 * 通用接口
 */
@RestController
@RequestMapping(value = "/common")
@Slf4j
public class CommonController {

    @Autowired
    private ClassServiceImpl classService;

    @Autowired
    private UserClassRelServiceImpl userClassRelService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private UserRoleServiceImpl userRoleService;

    //注入自己的redis工具类
    @Autowired
    private RedisUtil redisUtil;

    //jackson
    ObjectMapper mapper = new ObjectMapper();

    @RequestMapping("/error")
    public CommonResult<String> error() {
        return new CommonResult<>(233, "请求错误!");
    }

    /**
     * @param user 用户实体
     * @return
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/register")
    public CommonResult<String> Register(@RequestBody User user) throws NoSuchAlgorithmException {
        log.info("执行了===>CommonController中的register方法");
        //盐值
        String salt = UUID.randomUUID().toString().substring(0, 6);
        String newPwd = SaltEncryption.saltEncryption(user.getPassword(), salt);
        //设置加密
        user.setPassword(newPwd);
        user.setSalt(salt);
        user.setCreateDate(new Date());
        userService.save(user);
        //发放token令牌
        String token = TokenUtils.createToken(new TokenVo("1", user.getUsername(), newPwd));
        return new CommonResult<String>(200, "success", token);
    }

    /**
     * @param username 登录用户名
     * @return
     */
    @GetMapping("/check/{username}")
    public CommonResult<String> checkUsername(@PathVariable(value = "username") String username) {
        log.info("执行了===>CommonController中的checkUsername方法");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userService.getOne(wrapper);
        if (user == null) {
            return new CommonResult<>(200, "用户名可用");
        } else {
            return new CommonResult<>(233, "用户已存在");
        }
    }

    /**
     * @param username 登录用户名
     * @param password 用户密码
     * @return
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/login")
    public CommonResult<String> login(@RequestParam(value = "username") String username,
                                      @RequestParam(value = "password") String password) throws NoSuchAlgorithmException {
        log.info("执行了===>CommonController中的login方法");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userService.getOne(wrapper);
        if (user != null) {
            String newPwd = SaltEncryption.saltEncryption(password, user.getSalt());
            //对用户输入的密码加密后 对比数据库的密码 并且用户的状态是正常的
            if (newPwd.equals(user.getPassword()) && user.getStatus() == 1) {
                //发放token令牌
                String token = TokenUtils.createToken(new TokenVo(user.getRoleId() + "", user.getUsername(), newPwd));
                return new CommonResult<>(200, "success", token);
            } else {//密码错误 或者 账号封禁
                return new CommonResult<>(233, "账号密码错误,或用户状态异常");
            }
        } else {
            return new CommonResult<>(233, "用户不存在");
        }
    }

    @GetMapping("/logout")
    public CommonResult<String> logout() {
        log.info("执行了===>CommonController中的logout方法");
        return new CommonResult<>(200, "退出成功");
    }

    /**
     * @param request
     * @return
     */
    @GetMapping("/getMenu")
    public CommonResult<Object> getMenu(HttpServletRequest request) {
        log.info("执行了===>CommonController中的getMenu方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            if (redisUtil.get("menu:" + tokenVo.getRoleId()) != null) {
                return new CommonResult<>(200, "success", redisUtil.get("menu:" + tokenVo.getRoleId()));
            } else {
                String roleId = tokenVo.getRoleId();
                QueryWrapper<UserRole> wrapper = new QueryWrapper<>();
                wrapper.eq("role_id", roleId);
                UserRole userRole = userRoleService.getOne(wrapper);
                redisUtil.set("menu:" + tokenVo.getRoleId(), userRole.getMenuInfo(), 60 * 60 * 10 + new Random().nextInt(5) * 60 * 60);
                return new CommonResult<>(200, "success", userRole.getMenuInfo());
            }

        } else {
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param request
     * @return
     */
    @GetMapping("/checkToken")
    public CommonResult<TokenVo> checkToken(HttpServletRequest request) {
        log.info("执行了===>CommonController中的checkToken方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        if (tokenVo != null) {//有效token
            return new CommonResult<>(200, "success", tokenVo);
        } else {
            return new CommonResult<>(233, "token无效");
        }
    }

    /**
     * @param classId 班课号
     * @param className  班级名称
     * @param pageNo    查询页数
     * @param pageSize  页面大小
     * @return
     * @throws InterruptedException
     */
    @GetMapping("/getClass")
    @Transactional
    public CommonResult<Object> getClass(@RequestParam(required = false) String classId,
                                        @RequestParam(required = false) String className,
                                        Integer pageNo, Integer pageSize,HttpServletRequest request) throws InterruptedException {
        log.info("执行了===>CommonController中的getClass方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            String userName = tokenVo.getUsername();
            String userRole = tokenVo.getRoleId();
            //参数一是当前页，参数二是每页个数
            IPage<Class> classPage = new Page<>(pageNo, pageSize);
            //查询条件(可选)
            QueryWrapper<Class> wrapper = new QueryWrapper<>();
            if (!Objects.equals(userName, "") && userName != null && !userRole.equals("3")) {
                wrapper.apply("exists (select 1 from user_class_rel b where class.class_id = b.class_id and user_name = {0})", userName);
            }
            if (!Objects.equals(classId, "") && classId != null) {
                wrapper.like("class_id", classId);
            }
            if (!Objects.equals(className, "") && className != null) {
                wrapper.like("class_name", className);
            }
            classPage = classService.page(classPage, wrapper);
            List<Class> classes = classPage.getRecords();
            // 创建分页结果集
            Map<Object, Object> result = new HashMap<>();
            result.put("classes", classes);
            result.put("total", classPage.getTotal());
            return new CommonResult<>(200, "success", result);
        } else {
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param classes 班级实体
     * @return
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/addClass")
    public CommonResult<String> addClass(@RequestBody Class classes,HttpServletRequest request) throws NoSuchAlgorithmException {
        log.info("执行了===>CommonController中的addClass方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            String userName = tokenVo.getUsername();
            classes.setClassName(classes.getClassName());
            classes.setCreator(userName);
            classes.setCreateDate(new Date());
            boolean saveClass = classService.save(classes);
            UserClassRel userClassRel = new UserClassRel();
            userClassRel.setClassId(classes.getClassId().toString());
            userClassRel.setUserName(userName);
            userClassRel.setCreateDate(new Date());
            boolean saveUserClassRel = userClassRelService.save(userClassRel);
            return saveClass&&saveUserClassRel ? new CommonResult<>(200, "操作成功") : new CommonResult<>(233, "操作失败");
        }else {
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param classId 班课号
     * @return
     */
    @GetMapping("/deleteClass")
    @Transactional
    public CommonResult<String> deleteClass(@RequestParam String classId) {
        log.info("执行了===>CommonController中的deleteClass方法");
        boolean deleteClass = classService.removeById(Integer.parseInt(classId));
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("class_id",classId);
        boolean deleteUserClassRel = userClassRelService.remove(wrapper);
        return deleteClass&&deleteUserClassRel ? new CommonResult<>(200, "操作成功") : new CommonResult<>(233, "操作失败");
    }

    /**
     * @param classId 班课号
     * @return
     */
    @GetMapping("/exitClass")
    @Transactional
    public CommonResult<String> exitClass(@RequestParam String classId,HttpServletRequest request) {
        log.info("执行了===>CommonController中的exitClass方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            String userName = tokenVo.getUsername();
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("class_id", classId);
            wrapper.eq("user_name", userName);
            boolean exitUserClassRel = userClassRelService.remove(wrapper);
            return exitUserClassRel ? new CommonResult<>(200, "操作成功") : new CommonResult<>(233, "操作失败");
        }else{
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param userClassRel 用户班级关系实体
     * @return
     * @throws NoSuchAlgorithmException
     */
    @PostMapping("/joinClass")
    public CommonResult<String> addUser(@RequestBody UserClassRel userClassRel,HttpServletRequest request) throws NoSuchAlgorithmException {
        log.info("执行了===>CommonController中的joinClass方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            QueryWrapper<Class> wrapper = new QueryWrapper<>();
            wrapper.eq("class_id", userClassRel.getClassId());
            Class classes = classService.getOne(wrapper);
            if (classes == null) {
                return new CommonResult<>(233, "班级不存在！请检查班课号");
            } else {
                String userName = tokenVo.getUsername();
                QueryWrapper<UserClassRel> wrapperRel = new QueryWrapper<>();
                wrapperRel.eq("class_id", userClassRel.getClassId());
                wrapperRel.eq("user_name", userName);
                if(userClassRelService.getOne(wrapperRel) == null){
                    userClassRel.setClassId(userClassRel.getClassId());
                    userClassRel.setUserName(userName);
                    userClassRel.setCreateDate(new Date());
                    boolean saveUserClassRel = userClassRelService.save(userClassRel);
                    return saveUserClassRel ? new CommonResult<>(200, "操作成功") : new CommonResult<>(233, "操作失败");
                }else {
                    return  new CommonResult<>(233,"你已在该班级中！");
                }
            }
        }else {
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param classId 班课号
     * @param userName  用户名
     * @param pageNo    查询页数
     * @param pageSize  页面大小
     * @return
     * @throws InterruptedException
     */
    @GetMapping("/getClassMate")
    @Transactional
    public CommonResult<Object> getClassMate(@RequestParam String classId,
                                         @RequestParam(required = false) String userName,
                                         Integer pageNo, Integer pageSize,HttpServletRequest request) throws InterruptedException {
        log.info("执行了===>CommonController中的getClassMate方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        System.out.println(tokenVo);
        //有效token
        if (tokenVo != null) {
            //参数一是当前页，参数二是每页个数
            IPage<UserClassRel> classMatePage = new Page<>(pageNo, pageSize);
            //查询条件(可选)
            QueryWrapper<UserClassRel> wrapper = new QueryWrapper<>();
            if (!Objects.equals(classId, "") && classId != null) {
                wrapper.eq("class_id", classId);
            }
            if (!Objects.equals(userName, "") && userName != null) {
                wrapper.like("user_name", userName);
            }
            classMatePage = userClassRelService.page(classMatePage, wrapper);
            List<UserClassRel> userClassRels = classMatePage.getRecords();

            List<ClassMateInfo> classMateInfos = new ArrayList<>();
            for(UserClassRel classMate : userClassRels){
                //创建vo对象
                ClassMateInfo classMateInfo = new ClassMateInfo();
                //设置属性
                classMateInfo.setUserClassRel(classMate);
                //设置真实姓名
                String trueName = userService.getOne(new QueryWrapper<User>().eq("username",classMate.getUserName())).getTrueName();
                classMateInfo.setTrueName(trueName);
                //加入list中
                classMateInfos.add(classMateInfo);
            }

            // 创建分页结果集
            Map<Object, Object> result = new HashMap<>();
            result.put("classMateInfos", classMateInfos);
            result.put("total", classMatePage.getTotal());
            return new CommonResult<>(200, "success", result);
        } else {
            return new CommonResult<>(233, "认证信息有误,获取数据失败");
        }
    }

    /**
     * @param classId 班课号
     * @param userName 用户名
     * @return
     */
    @GetMapping("/deleteClassMate")
    @Transactional
    public CommonResult<String> deleteClassMate(@RequestParam String classId,@RequestParam String userName) {
        log.info("执行了===>CommonController中的deleteClassMate方法");
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("class_id",classId);
        wrapper.eq("user_name",userName);
        boolean deleteUserClassRel = userClassRelService.remove(wrapper);
        return deleteUserClassRel ? new CommonResult<>(200, "操作成功") : new CommonResult<>(233, "操作失败");
    }

    @GetMapping("/getCurrentUser")
    public CommonResult<User> getCurrentUser(HttpServletRequest request) {
        log.info("执行了===>CommonController中的getCurrentUser方法");
        //工具类验证token是否有效 有效返回tokenVo对象,否则返回null
        TokenVo tokenVo = new CheckToken().checkToken(request, userService);
        User user = userService.getOne(new QueryWrapper<User>().eq("username", tokenVo.getUsername()));
        return new CommonResult<>(200, "查询当前用户成功", user);
    }
}
